import base64
import hashlib
import json
import logging
import traceback
from django.conf import settings
from django.contrib.auth import get_user_model
from scaffold_toolkit.views import AjaxView
from django.utils import timezone
from oauth2 import pydes

User = get_user_model()
logger = logging.getLogger('ghouse')


def _decode_pwd(tag, pwd):
    decode_key = str(tag[0:3] + tag[5] + tag[8] + tag[11] + tag[15:23] + tag[31] + tag[35])
    encoded_pwd = base64.decodebytes(pwd.encode('utf-8'))
    return pydes.triple_des(decode_key, padmode=pydes.PAD_PKCS5).decrypt(encoded_pwd)


class ApiView(AjaxView):
    """
    Api
    """
    request_sign_fields = ['msg', 'username', 'nonce', 'tag']
    request_msg = ''

    response_sign_fields = ['msg', 'username', 'nonce', 'tag']
    response_msg = ''

    login_required = False

    def process_request(self, request):
        if self.login_required and not request.user.is_authenticated():
            return {'success': False, 'status': 407, 'status-text': '未登录'}
        try:
            req_data = json.loads(request.body.decode('utf-8'))
            self.kwargs = req_data
        except ValueError:
            resp = {'msg': '', 'success': False, 'nonce': timezone.now().microsecond,
                    'status': 400, 'status-text': 'Bad Request'}
            if 'username' not in resp:
                resp['username'] = req_data['username']
            resp['sign'] = self._get_sign(resp, ['msg', 'username', 'nonce', 'tag'])
            return resp
        if req_data['sign'] != self._get_sign(req_data, self.request_sign_fields):
            iloc = req_data['msg'].index('-')
            resp_msg = req_data['msg'][:iloc] + '-resp' if iloc >= 0 else ''
            resp = {'msg': resp_msg, 'success': False, 'nonce': timezone.now().microsecond,
                    'status': 404, 'status-text': 'Sign Error'}
            if 'username' not in resp:
                resp['username'] = req_data['username']
            resp['sign'] = self._get_sign(resp, ['msg', 'username' 'nonce', 'tag'])
            return resp
        resp = self.get_result(**req_data)
        if 'success' not in resp:
            resp['success'] = True
        if 'nonce' not in resp and 'nonce' in self.response_sign_fields:
            resp['nonce'] = timezone.now().microsecond
        if 'msg' not in resp:
            resp['msg'] = self.response_msg
        if 'status' not in resp:
            resp['status'] = 200
        if 'status-text' not in resp:
            resp['status-text'] = 'ok'
        if 'username' not in resp:
            resp['username'] = req_data['username']
        resp['sign'] = self._get_sign(resp, self.response_sign_fields)
        return resp

    def post_ajax(self, request, *args, **kwargs):
        req_at = timezone.now()
        try:
            r = self.process_request(request)
        except Exception as e:
            r = {'status': 500, 'status-text': traceback.format_exc()[:200]}
        resp_at = timezone.now()
        return self.render_json_response(r)

    def _get_sign(self, data, fields):
        """
        计算签名
        :param data:
        :param fields:
        :return:
        """
        to_sign = ''.join(
            [settings.TAG if item == 'tag' else str(data[item]) if item in data else '' for item in fields])
        md5 = hashlib.md5(to_sign.encode('utf-8'))
        return md5.hexdigest()

    def get_result(self, **kwargs):
        """
        处理请求
        :return: 处理的结果
        """
        raise NotImplementedError()

    @property
    def host(self):
        return self.request.get_host()
